<?php
namespace service;

use think\Cache;
use think\Log;

class BaiduAiService
{
	// 人脸组ID，只用一个组
	const FACE_GROUP_ID = 1;

	const FACE_MATCH_SCORE = 85;

	const CLIENT_ID     = 'dRiwNIhpYcMic3TbzmD9sRKz';
	const CLIENT_SECRET = 'kOh7FlN8eC18jkCWQIh34rYa1depEkqz';

	protected static $accessTokenUrl = 'https://aip.baidubce.com/oauth/2.0/token';

	protected static $baseUrl = 'https://aip.baidubce.com/rest/2.0/face/v3';

	/**
	 * [getAccessToken description]
	 * @Author   FW
	 * @DateTime 2021-04-08
	 * @Email    123763712@qq.com
	 * @return   [type]           [description]
	 */
	public static function getAccessToken ()
	{
		$accessToken = Cache::get('baiduai_access_token');
		if ( empty($accessToken) ) {
			$params  = sprintf('?grant_type=client_credentials&client_id=%s&client_secret=%s',static::CLIENT_ID,static::CLIENT_SECRET);
			$result  = self::curlRequest( static::$accessTokenUrl . $params);

			if ( isset($result['access_token']) ) {
				$accessToken = $result['access_token'];
				# access token有效期30天，缓存29天提前重新申请
				Cache::set('baiduai_access_token',$accessToken, 3600 * 24 * 29);
			}
		}
		return $accessToken;
	}

	/**
	 * 注册人脸
	 * @Author   FW
	 * @DateTime 2021-04-26
	 * @Email    123763712@qq.com
	 * @param    array            $params [description]
	 * @return   [type]                   [description]
	 */
	public static function registerFace ( $params = [] , $callback = null )
	{
		if ( !isset($params['image']) ) return false;
		if ( !isset($params['image_type']) || !\in_array($params['image_type'] , ['BASE64','URL','FACE_TOKEN']) ) return false;
		if ( !isset($params['user_id']) ) return false;

		$params['group_id']  = static::FACE_GROUP_ID;

		$params['user_id']   = 'UID_' . $params['user_id'];

		$result  = self::curlRequest( static::$baseUrl . '/faceset/user/add?access_token=' . static::getAccessToken()  , $params , 'POST');

		if ( isset($result['result']) ) {
			$face_token = $result['result']['face_token'] ?? '';
			if ( $face_token ) {
				if ( is_callable($callback) ) {
					return $callback($face_token);
				}
			}
		}
	}

	/**
	 * 识别人脸
	 * @Author   FW
	 * @DateTime 2021-04-26
	 * @Email    123763712@qq.com
	 * @param    array            $params   [description]
	 * @param    [type]           $callback [description]
	 * @return   [type]                     [description]
	 */
	public static function identifyFace ( $params = [] , $callback = null )
	{
		if ( !isset($params['image']) ) return false;
		if ( !isset($params['image_type']) || !\in_array($params['image_type'] , ['BASE64','URL','FACE_TOKEN']) ) return false;

		$params['group_id_list']  = static::FACE_GROUP_ID;

		$result  = self::curlRequest( static::$baseUrl . '/search?access_token=' . static::getAccessToken()  , $params , 'POST');

		if ( isset($result['result']) ) {
			$user_list = $result['result']['user_list'] ?? [];
			if ( $user_list ) {
				if ( is_callable($callback) ) {
					$user_id = 0;
					foreach ( $user_list as $user ) {
						if ( $user['score'] > static::FACE_MATCH_SCORE ) {
							$user_id = str_replace('UID_', '', $user['user_id']);
							break;
						}
					}

					return $callback($user_id);
				}
			}
		}
		return false;
	}

	/**
	 * 生成PNG文件
	 * @Author   FW
	 * @DateTime 2021-04-26
	 * @Email    123763712@qq.com
	 * @param    [type]           $base_img [description]
	 * @param    string           $type     [description]
	 * @param    integer          $stu_id   [description]
	 * @return   [type]                     [description]
	 */
	public static function saveAsPng ($base_img , $type='register',$stu_id=0 )
    {
        $base_img = str_replace('data:image/png;base64,', '', $base_img);
        $path = UPLOAD_PATH . 'face_img/' . $type . '/';
        if ( !is_dir($path) ) {
            mkdir($path,0755,true);
        }

        $stu_id = $stu_id>0 ? $stu_id : time();
        $output_file = $stu_id.'.png';
        $path = $path.$output_file;
        if ( !file_put_contents($path, base64_decode($base_img)) ) return false;

        return $path;
    }

	/**
	 * @Description: curl请求
	 * @Author: FW
	 * @param $url
	 * @param null $data
	 * @param string $method
	 * @param array $header
	 * @param bool $https
	 * @param int $timeout
	 * @return mixed
	 */
	public static function curlRequest($url, $data=null, $method='get', $header = array("content-type: application/json"), $https=true, $timeout = 5 , $josn2Arr = true){
	    $method = strtoupper($method);
	    $ch = curl_init();//初始化
	    curl_setopt($ch, CURLOPT_URL, $url);//访问的URL
	    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//只获取页面内容，但不输出
	    if($https){
	        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//https请求 不验证证书
	        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//https请求 不验证HOST
	    }

	    if ($method != "GET") {
	        if($method == 'POST'){
	            curl_setopt($ch, CURLOPT_POST, true);//请求方式为post请求
	            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));//请求数据
	        }
	        if ($method == 'PUT' || strtoupper($method) == 'DELETE') {
	            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); //设置请求方式
	        }

			Log::info('curl send data:' .  json_encode($data));
	    }
	    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
	    curl_setopt($ch, CURLOPT_HTTPHEADER, $header); //模拟的header头
	    //curl_setopt($ch, CURLOPT_HEADER, false);//设置不需要头信息


	    $result = curl_exec($ch);//执行请求
	    curl_close($ch);//关闭curl，释放资源

	    if ( $josn2Arr && is_string($result) ) {
	    	$result = json_decode($result,true);

	    	if ( json_last_error() > 0 ) {
	    		return [];
	    	}
	    }
	    Log::info('curl responde data:' .  json_encode($result));
	    return $result;
	}
}